#include "barcode.h"
#include <stdio.h>
#include <string.h>
#include "common.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "../../app/ack_msg.h"
#include "msg_def.h"
#include "../data_proc/board_data_proc.h"


const char * strPurifyReagent[2] = 
{
    "C1-01",
    "C2-01",
};

const char * strSampleBarcode[4] = 
{
    "D1-01",
    "E1-01",
    "D2-01",
    "E2-01",
};


CBarcode::CBarcode()
{
    memset(m_bar_code_all,0,sizeof(barcode_str*)*MAX_CHAN_NUM_BAR);

    memset(m_currBarcodeNum,0,sizeof(int)*MAX_CHAN_NUM_BAR);

    memset(m_barcodeStrBuff,0,sizeof(barcode_str)*MAX_CHAN_NUM_BAR);

    memset(m_CurrIndexStrBuff,0,sizeof(int)*MAX_CHAN_NUM_BAR);
}

CBarcode::~CBarcode()
{
    for(int i=0;i<MAX_CHAN_NUM_BAR;i++)
    {
        if(m_bar_code_all[i])
        {
            delete [] m_bar_code_all[i];
            m_bar_code_all[i] = NULL;
        }
    }
    memset(m_bar_code_all,0,sizeof(barcode_str*)*MAX_CHAN_NUM_BAR);

    memset(m_currBarcodeNum,0,sizeof(int)*MAX_CHAN_NUM_BAR);

    memset(m_barcodeStrBuff,0,sizeof(barcode_str)*MAX_CHAN_NUM_BAR);

    memset(m_CurrIndexStrBuff,0,sizeof(int)*MAX_CHAN_NUM_BAR);
}

int CBarcode::init_one_chan(int chanNum)
{
    if(m_bar_code_all[chanNum] == NULL)
    {
       m_bar_code_all[chanNum] = new barcode_str[Barcode_Num[chanNum]]; 
    }

    memset(m_bar_code_all[chanNum],0,sizeof(barcode_str)*Barcode_Num[chanNum]);
    m_currBarcodeNum[chanNum] = 0;


    memset(&m_barcodeStrBuff[chanNum],0,sizeof(barcode_str));
    m_CurrIndexStrBuff[chanNum] = 0;   
}


int CBarcode::addPartStr(unsigned char chanNum,unsigned char typeIn,unsigned char * strIn, unsigned char lenStr)
{
    //printf("enter in addPartStr,chanNum:%d,typeIn is %d\n",chanNum,typeIn);
    if(typeIn == BARCODE_FIRST_PART)
    {
        if(m_CurrIndexStrBuff[chanNum])
        {
           m_currBarcodeNum[chanNum] ++;
           m_CurrIndexStrBuff[chanNum] = 0; 
        }
    }
    
    int currNumBarcode = m_currBarcodeNum[chanNum];

    if(m_bar_code_all[chanNum]==NULL)
    {
        printf("m_bar_code_all[chanNum] is NULL\n");
        return 1;
    }

    unsigned short sumThisPart = 0;
    for(int i=0;i<lenStr;i++)
    {
        sumThisPart += strIn[i];
    }

    if((lenStr + m_CurrIndexStrBuff[chanNum]) <= MAX_BAR_STR_LEN
      && currNumBarcode < Barcode_Num[chanNum])
    {
        memcpy(m_bar_code_all[chanNum][currNumBarcode].barStr+m_CurrIndexStrBuff[chanNum],strIn,lenStr);
        m_bar_code_all[chanNum][currNumBarcode].checkCode += sumThisPart;
        m_CurrIndexStrBuff[chanNum] += lenStr;
    }   

    if(typeIn == BARCODE_LAST_PART)
    {
        int isBarCodeStrExist = 0;
        int checkCodeThisStr = m_bar_code_all[chanNum][currNumBarcode].checkCode;

        printf("barcode recv:%s\n",m_bar_code_all[chanNum][currNumBarcode].barStr);
        
        if(chanNum>=2)
        {//for vertical barcode scanner.
            writeToFile((chanNum << 4) + 0);

            report_up_msg reportMsg;
            memset(&reportMsg,0,sizeof(report_up_msg));
            reportMsg.type = NOTIFY_SCAN_CODE;
            reportMsg.dataLen = sizeof(int);
            reportMsg.un_msg_data.barcodeChan = (chanNum << 4) + 0;
            sendSockNotifyMsg(&reportMsg); 

            recvDataEleCtl stLuaAckData;

            stLuaAckData.frameType = CHECK_MOVE_END;
            stLuaAckData.sid = SUBBOARD_BASE + (SCANCODE_BOARD<<5) + chanNum;
            sendAckToLua(&stLuaAckData);
        }
        else
        {
            for(int i=(currNumBarcode-1);i>=0;i--)
            {
                if(m_bar_code_all[chanNum][i].checkCode
                == checkCodeThisStr)
                {
                    isBarCodeStrExist = 1;
                    break;
                }
            }

            if(!isBarCodeStrExist)
            {
                //did not find the same string in strings received previously.
                m_currBarcodeNum[chanNum] ++;
            }

            //printf("chanNum:%d,BarcodeNum:%d\n",chanNum,m_currBarcodeNum[chanNum]);
            m_CurrIndexStrBuff[chanNum] = 0;
            m_bar_code_all[chanNum][m_currBarcodeNum[chanNum]].checkCode = 0;
        }
        //send the string to grpc if need.
    }

    return 0;    
} 

int CBarcode::stop_one_chan(int chanNum)
{
    if(chanNum>=MAX_CHAN_NUM_BAR)
    {
        return 1;
    }
    barcode_str * ptrStStr = m_bar_code_all[chanNum];
    printf("total %d barcode of chan[%d]\n",m_currBarcodeNum[chanNum],chanNum);
    int numLast = (m_currBarcodeNum[chanNum] > Barcode_Num[chanNum])?Barcode_Num[chanNum]:m_currBarcodeNum[chanNum];
    for(int i=0;i<numLast;i++)
    {
        printf("%d,%s\n",i,ptrStStr->barStr);
        ptrStStr++;
    }
    writeToFile(chanNum);
    report_up_msg reportMsg;
    memset(&reportMsg,0,sizeof(report_up_msg));
    reportMsg.type = NOTIFY_SCAN_CODE;
    reportMsg.dataLen = sizeof(int);
    reportMsg.un_msg_data.barcodeChan = chanNum;
    sendSockNotifyMsg(&reportMsg); 
    
    m_currBarcodeNum[chanNum] = 0;
    m_CurrIndexStrBuff[chanNum] = 0;

    return 0;
}

int CBarcode::scan_end(int drawerId)
{
    printf("enter in CBarcode::scan_end\n");
    int scanChan = -1;
    const char * pStrStart = NULL;
    int subId = 0;
    if( drawerId >= I_DRAWER_PURIFY_REAGENT1
      && drawerId <= I_DRAWER_PURIFY_REAGENT2)
    {
        scanChan = 0;
        subId = drawerId-I_DRAWER_PURIFY_REAGENT1;
        pStrStart = strPurifyReagent[drawerId-I_DRAWER_PURIFY_REAGENT1];
    }
    else if(drawerId >= I_DRAWER_SAMPLE1
      && drawerId <= I_DRAWER_SAMPLE4)
    {
        scanChan = 1;
        subId = drawerId-I_DRAWER_SAMPLE1;
        pStrStart = strSampleBarcode[drawerId-I_DRAWER_SAMPLE1];
    }
    // else if(drawerId >= I_DRAWER_PCR_REAGENT1
    //   && drawerId <= I_DRAWER_PCR_REAGENT2
    // )
    // {
    //     scanChan = 2;
    // }
    // else if(drawerId == I_DRAWER_HEAT_FILM)
    // {
    //     scanChan = 3;
    // }

    if(scanChan == -1)
    {
        printf("it is impossible to have barcode for this drawer\n");
        return 1;
    }

    if(m_currBarcodeNum[scanChan] == 0)
    {
        printf("error occurred, no barcode scan out\n");
        return 2;
    }
    
    barcode_str * ptrStStr = m_bar_code_all[scanChan];
    printf("recv str:%c%c, standard str:%s\n",ptrStStr->barStr[0],ptrStStr->barStr[1],pStrStart);
    if(ptrStStr->barStr[0] == pStrStart[0]
      &&ptrStStr->barStr[1] == pStrStart[1])
    {
        //write all the barcode to file and send msg to report up
        writeToFile((scanChan << 4) + subId);

        report_up_msg reportMsg;
        memset(&reportMsg,0,sizeof(report_up_msg));
        reportMsg.type = NOTIFY_SCAN_CODE;
        reportMsg.dataLen = sizeof(int);
        reportMsg.un_msg_data.barcodeChan = (scanChan << 4) + subId;
        sendSockNotifyMsg(&reportMsg);       

    }
    else
    {
        // alarm here
        printf("drawer enter in the wrong groove\n");
    }

    return 0;
}


void CBarcode::writeToFile(int chanNumIn)
{
    char filePath[256] = {0};
    int chanNum = (chanNumIn>>4)&0x0f;
    int subId = chanNumIn&0x0f;
    sprintf(filePath,"%schan_%d_%d.txt",FILE_BARCODE_PATH,chanNum,subId);

    int fd = open(filePath,O_CREAT|O_TRUNC|O_RDWR,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);

    if(fd == -1)
    {
        printf("open file to write barcode failed\n");
        return;
    }
    
    barcode_str * ptrStStr = m_bar_code_all[chanNum];

    // int writeRet = write(fd,"string test",11);

    // if(writeRet == 11)
    // {
    //     printf("write test string success\n");
        
    // }
    // else 
    // {
    //     printf("write test string failed, ret:%d\n",writeRet);
    //     perror("write file failed\n");
    // }

    int numLast = (m_currBarcodeNum[chanNum] > Barcode_Num[chanNum])?Barcode_Num[chanNum]:m_currBarcodeNum[chanNum];
    for(int i=0;i<numLast;i++)
    {
        printf("%d,%s\n",i,ptrStStr->barStr);
        write(fd,ptrStStr->barStr,strlen(ptrStStr->barStr));
        ptrStStr++;
    }

    close(fd);
}

CBarcode * g_barcode_handle = NULL;